#include <dp/thread/CriticalSection.h>

//Thuat ngu: undefined behavior.

DP_BEGIN

CriticalSection::CriticalSection(const char *name)
	: m_nLockCount(0)
	, m_name(name)
{
	// MS: In low memory situations, InitializeCriticalSection can raise a STATUS_NO_MEMORY exception.
	InitializeCriticalSection(&criticalSection);
}

void CriticalSection::Lock()
{
	// MS: The EnterCriticalSection function waits for ownership of the specified critical section object.
	// MS: The function returns when the calling thread is granted ownership.
	m_nLockCount++;
	EnterCriticalSection(&criticalSection);
}

bool CriticalSection::TryLock()
{
	bool ret = (TryEnterCriticalSection(&criticalSection) != 0);
	if(ret)
		m_nLockCount++;

	return ret;
}

void CriticalSection::Unlock()
{
	if(0 == m_nLockCount)
		DP_FALTAL("Donot call Unlock if you have not call Lock.");

	m_nLockCount--;

	// MS: If a thread calls LeaveCriticalSection when it does not have ownership of the specified critical
	// section object, an error occurs that may cause another thread using EnterCriticalSection to wait
	// indefinitely.
	LeaveCriticalSection(&criticalSection);
}

CriticalSection::~CriticalSection()
{
	if(m_nLockCount)
		DP_FALTAL("You must leave (unlock) all thread before dtor.");

	// MS: The DeleteCriticalSection function releases all resources used by an unowned critical section
	// object.
	DeleteCriticalSection(&criticalSection);
}

DP_END
